package com.cencat.order.controller;

import com.cencat.common.annotation.Log;
import com.cencat.common.core.controller.BaseController;
import com.cencat.common.core.domain.AjaxResult;
import com.cencat.common.core.page.TableDataInfo;
import com.cencat.common.enums.BusinessType;
import com.cencat.common.utils.poi.ExcelUtil;
import com.cencat.order.domain.DeliveryOrder;
import com.cencat.order.domain.DeliveryTrack;
import com.cencat.order.domain.DeliveryFeedback;
import com.cencat.order.domain.vo.DeliveryVO;
import com.cencat.order.domain.vo.DeliveryTrackVO;
import com.cencat.order.domain.vo.DeliveryStatisticsVO;
import com.cencat.order.domain.vo.DeliveryMonitorVO;
import com.cencat.order.domain.dto.DeliveryCreateDTO;
import com.cencat.order.domain.dto.DeliveryUpdateDTO;
import com.cencat.order.domain.dto.DeliveryTrackDTO;
import com.cencat.order.domain.dto.DeliveryFeedbackDTO;
import com.cencat.order.service.IDeliveryService;
import com.cencat.order.service.IDeliveryTrackService;
import com.cencat.order.service.IDeliveryFeedbackService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * 配送跟踪与反馈系统控制器
 * 
 * @author cencat
 * @date 2024-01-20
 */
@Tag(name = "配送跟踪管理", description = "配送跟踪与反馈系统核心功能接口")
@RestController
@RequestMapping("/delivery")
@RequiredArgsConstructor
@Validated
public class DeliveryController extends BaseController {

    private final IDeliveryService deliveryService;
    private final IDeliveryTrackService deliveryTrackService;
    private final IDeliveryFeedbackService deliveryFeedbackService;

    /**
     * 创建配送订单
     */
    @Operation(summary = "创建配送订单", description = "创建新的配送订单")
    @PreAuthorize("@ss.hasPermi('delivery:create')")
    @Log(title = "配送订单", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult createDelivery(@Valid @RequestBody DeliveryCreateDTO createDTO) {
        DeliveryVO deliveryVO = deliveryService.createDelivery(createDTO);
        return success(deliveryVO);
    }

    /**
     * 查询配送订单列表
     */
    @Operation(summary = "查询配送订单列表", description = "分页查询配送订单信息")
    @PreAuthorize("@ss.hasPermi('delivery:list')")
    @GetMapping("/list")
    public TableDataInfo list(DeliveryOrder deliveryOrder) {
        startPage();
        List<DeliveryOrder> list = deliveryService.selectDeliveryList(deliveryOrder);
        return getDataTable(list);
    }

    /**
     * 获取配送订单详情
     */
    @Operation(summary = "获取配送订单详情", description = "根据配送订单ID获取详细信息")
    @PreAuthorize("@ss.hasPermi('delivery:query')")
    @GetMapping(value = "/{deliveryId}")
    public AjaxResult getInfo(@Parameter(description = "配送订单ID") @PathVariable Long deliveryId) {
        DeliveryVO deliveryVO = deliveryService.getDeliveryDetail(deliveryId);
        return success(deliveryVO);
    }

    /**
     * 修改配送订单
     */
    @Operation(summary = "修改配送订单", description = "更新配送订单信息")
    @PreAuthorize("@ss.hasPermi('delivery:edit')")
    @Log(title = "配送订单", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@Valid @RequestBody DeliveryUpdateDTO updateDTO) {
        boolean result = deliveryService.updateDelivery(updateDTO);
        return toAjax(result);
    }

    /**
     * 删除配送订单
     */
    @Operation(summary = "删除配送订单", description = "删除指定配送订单")
    @PreAuthorize("@ss.hasPermi('delivery:remove')")
    @Log(title = "配送订单", businessType = BusinessType.DELETE)
    @DeleteMapping("/{deliveryIds}")
    public AjaxResult remove(@Parameter(description = "配送订单ID数组") @PathVariable Long[] deliveryIds) {
        boolean result = deliveryService.deleteDeliveryByIds(deliveryIds);
        return toAjax(result);
    }

    /**
     * 更新配送状态
     */
    @Operation(summary = "更新配送状态", description = "更新配送订单的执行状态")
    @PreAuthorize("@ss.hasPermi('delivery:status')")
    @Log(title = "配送状态", businessType = BusinessType.UPDATE)
    @PutMapping("/status")
    public AjaxResult updateStatus(@RequestParam Long deliveryId,
                                  @RequestParam String status,
                                  @RequestParam(required = false) String remark,
                                  @RequestParam(required = false) Double longitude,
                                  @RequestParam(required = false) Double latitude) {
        boolean result = deliveryService.updateDeliveryStatus(deliveryId, status, remark, longitude, latitude);
        return toAjax(result);
    }

    /**
     * 司机接单
     */
    @Operation(summary = "司机接单", description = "司机确认接受配送订单")
    @PostMapping("/accept")
    public AjaxResult acceptDelivery(@RequestParam Long deliveryId,
                                    @RequestParam Long driverId) {
        boolean result = deliveryService.acceptDelivery(deliveryId, driverId);
        return toAjax(result);
    }

    /**
     * 开始配送
     */
    @Operation(summary = "开始配送", description = "司机开始执行配送任务")
    @PostMapping("/start")
    public AjaxResult startDelivery(@RequestParam Long deliveryId,
                                   @RequestParam Long driverId,
                                   @RequestParam(required = false) Double longitude,
                                   @RequestParam(required = false) Double latitude) {
        boolean result = deliveryService.startDelivery(deliveryId, driverId, longitude, latitude);
        return toAjax(result);
    }

    /**
     * 到达取货点
     */
    @Operation(summary = "到达取货点", description = "司机到达商家取货点")
    @PostMapping("/arrive-pickup")
    public AjaxResult arrivePickup(@RequestParam Long deliveryId,
                                  @RequestParam Long driverId,
                                  @RequestParam Double longitude,
                                  @RequestParam Double latitude,
                                  @RequestParam(required = false) String remark) {
        boolean result = deliveryService.arrivePickup(deliveryId, driverId, longitude, latitude, remark);
        return toAjax(result);
    }

    /**
     * 完成取货
     */
    @Operation(summary = "完成取货", description = "司机完成商品取货")
    @PostMapping("/pickup-complete")
    public AjaxResult pickupComplete(@RequestParam Long deliveryId,
                                    @RequestParam Long driverId,
                                    @RequestParam(required = false) String goodsInfo,
                                    @RequestParam(required = false) String photos) {
        boolean result = deliveryService.pickupComplete(deliveryId, driverId, goodsInfo, photos);
        return toAjax(result);
    }

    /**
     * 到达配送点
     */
    @Operation(summary = "到达配送点", description = "司机到达客户配送点")
    @PostMapping("/arrive-delivery")
    public AjaxResult arriveDelivery(@RequestParam Long deliveryId,
                                    @RequestParam Long driverId,
                                    @RequestParam Double longitude,
                                    @RequestParam Double latitude,
                                    @RequestParam(required = false) String remark) {
        boolean result = deliveryService.arriveDelivery(deliveryId, driverId, longitude, latitude, remark);
        return toAjax(result);
    }

    /**
     * 完成配送
     */
    @Operation(summary = "完成配送", description = "司机完成配送任务")
    @PostMapping("/complete")
    public AjaxResult completeDelivery(@RequestParam Long deliveryId,
                                      @RequestParam Long driverId,
                                      @RequestParam(required = false) String signaturePhoto,
                                      @RequestParam(required = false) String deliveryPhoto,
                                      @RequestParam(required = false) String remark) {
        boolean result = deliveryService.completeDelivery(deliveryId, driverId, signaturePhoto, deliveryPhoto, remark);
        return toAjax(result);
    }

    /**
     * 配送异常上报
     */
    @Operation(summary = "配送异常上报", description = "司机上报配送过程中的异常情况")
    @PostMapping("/report-exception")
    public AjaxResult reportException(@RequestParam Long deliveryId,
                                     @RequestParam Long driverId,
                                     @RequestParam String exceptionType,
                                     @RequestParam String description,
                                     @RequestParam(required = false) String photos,
                                     @RequestParam(required = false) Double longitude,
                                     @RequestParam(required = false) Double latitude) {
        boolean result = deliveryService.reportException(deliveryId, driverId, exceptionType, description, photos, longitude, latitude);
        return toAjax(result);
    }

    /**
     * 实时位置跟踪
     */
    @Operation(summary = "实时位置跟踪", description = "获取配送订单的实时位置信息")
    @PreAuthorize("@ss.hasPermi('delivery:track')")
    @GetMapping("/track/{deliveryId}")
    public AjaxResult getTrackInfo(@Parameter(description = "配送订单ID") @PathVariable Long deliveryId) {
        DeliveryTrackVO trackVO = deliveryTrackService.getTrackInfo(deliveryId);
        return success(trackVO);
    }

    /**
     * 更新位置信息
     */
    @Operation(summary = "更新位置信息", description = "司机实时更新位置信息")
    @PostMapping("/update-location")
    public AjaxResult updateLocation(@RequestParam Long deliveryId,
                                    @RequestParam Long driverId,
                                    @RequestParam Double longitude,
                                    @RequestParam Double latitude,
                                    @RequestParam(required = false) Double speed,
                                    @RequestParam(required = false) String direction) {
        boolean result = deliveryTrackService.updateLocation(deliveryId, driverId, longitude, latitude, speed, direction);
        return toAjax(result);
    }

    /**
     * 获取配送轨迹
     */
    @Operation(summary = "获取配送轨迹", description = "获取配送订单的完整轨迹信息")
    @PreAuthorize("@ss.hasPermi('delivery:track:history')")
    @GetMapping("/track-history/{deliveryId}")
    public AjaxResult getTrackHistory(@Parameter(description = "配送订单ID") @PathVariable Long deliveryId,
                                     @RequestParam(required = false) String startTime,
                                     @RequestParam(required = false) String endTime) {
        List<DeliveryTrack> trackHistory = deliveryTrackService.getTrackHistory(deliveryId, startTime, endTime);
        return success(trackHistory);
    }

    /**
     * 批量获取配送状态
     */
    @Operation(summary = "批量获取配送状态", description = "批量获取多个配送订单的状态")
    @PreAuthorize("@ss.hasPermi('delivery:batch:status')")
    @PostMapping("/batch-status")
    public AjaxResult getBatchStatus(@RequestParam Long[] deliveryIds) {
        List<Map<String, Object>> statusList = deliveryService.getBatchStatus(deliveryIds);
        return success(statusList);
    }

    /**
     * 配送反馈管理
     */
    @Operation(summary = "提交配送反馈", description = "客户或司机提交配送反馈")
    @PostMapping("/feedback")
    public AjaxResult submitFeedback(@Valid @RequestBody DeliveryFeedbackDTO feedbackDTO) {
        DeliveryFeedback feedback = deliveryFeedbackService.submitFeedback(feedbackDTO);
        return success("反馈提交成功", feedback.getId());
    }

    /**
     * 查询配送反馈列表
     */
    @Operation(summary = "查询配送反馈列表", description = "分页查询配送反馈信息")
    @PreAuthorize("@ss.hasPermi('delivery:feedback:list')")
    @GetMapping("/feedback/list")
    public TableDataInfo getFeedbackList(DeliveryFeedback deliveryFeedback) {
        startPage();
        List<DeliveryFeedback> list = deliveryFeedbackService.selectFeedbackList(deliveryFeedback);
        return getDataTable(list);
    }

    /**
     * 处理配送反馈
     */
    @Operation(summary = "处理配送反馈", description = "管理员处理配送反馈")
    @PreAuthorize("@ss.hasPermi('delivery:feedback:handle')")
    @Log(title = "配送反馈", businessType = BusinessType.UPDATE)
    @PutMapping("/feedback/handle")
    public AjaxResult handleFeedback(@RequestParam Long feedbackId,
                                    @RequestParam String handleResult,
                                    @RequestParam(required = false) String handleRemark) {
        boolean result = deliveryFeedbackService.handleFeedback(feedbackId, handleResult, handleRemark);
        return toAjax(result);
    }

    /**
     * 配送评价
     */
    @Operation(summary = "配送评价", description = "客户对配送服务进行评价")
    @PostMapping("/evaluate")
    public AjaxResult evaluateDelivery(@RequestParam Long deliveryId,
                                      @RequestParam Long customerId,
                                      @RequestParam Integer rating,
                                      @RequestParam(required = false) String comment,
                                      @RequestParam(required = false) String tags) {
        boolean result = deliveryService.evaluateDelivery(deliveryId, customerId, rating, comment, tags);
        return toAjax(result);
    }

    /**
     * 获取配送评价
     */
    @Operation(summary = "获取配送评价", description = "获取配送订单的评价信息")
    @PreAuthorize("@ss.hasPermi('delivery:evaluation:query')")
    @GetMapping("/evaluation/{deliveryId}")
    public AjaxResult getEvaluation(@Parameter(description = "配送订单ID") @PathVariable Long deliveryId) {
        Map<String, Object> evaluation = deliveryService.getEvaluation(deliveryId);
        return success(evaluation);
    }

    /**
     * 配送统计信息
     */
    @Operation(summary = "配送统计", description = "获取配送统计数据")
    @PreAuthorize("@ss.hasPermi('delivery:statistics')")
    @GetMapping("/statistics")
    public AjaxResult getStatistics(@RequestParam(required = false) String startDate,
                                   @RequestParam(required = false) String endDate,
                                   @RequestParam(required = false) String dimension,
                                   @RequestParam(required = false) Long driverId) {
        DeliveryStatisticsVO statistics = deliveryService.getDeliveryStatistics(startDate, endDate, dimension, driverId);
        return success(statistics);
    }

    /**
     * 配送效率分析
     */
    @Operation(summary = "效率分析", description = "分析配送效率和时效性")
    @PreAuthorize("@ss.hasPermi('delivery:analyze')")
    @GetMapping("/efficiency-analysis")
    public AjaxResult getEfficiencyAnalysis(@RequestParam(required = false) String startDate,
                                           @RequestParam(required = false) String endDate,
                                           @RequestParam(required = false) String groupBy,
                                           @RequestParam(required = false) String region) {
        Map<String, Object> analysis = deliveryService.getEfficiencyAnalysis(startDate, endDate, groupBy, region);
        return success(analysis);
    }

    /**
     * 配送实时监控
     */
    @Operation(summary = "实时监控", description = "获取配送系统实时监控数据")
    @PreAuthorize("@ss.hasPermi('delivery:monitor')")
    @GetMapping("/monitor")
    public AjaxResult getMonitorData(@RequestParam(required = false) String region,
                                    @RequestParam(required = false) String status) {
        DeliveryMonitorVO monitorData = deliveryService.getMonitorData(region, status);
        return success(monitorData);
    }

    /**
     * 配送路径优化
     */
    @Operation(summary = "路径优化", description = "优化配送路径规划")
    @PreAuthorize("@ss.hasPermi('delivery:optimize')")
    @PostMapping("/optimize-route")
    public AjaxResult optimizeRoute(@RequestParam Long deliveryId,
                                   @RequestParam(required = false) String optimizeType) {
        Map<String, Object> result = deliveryService.optimizeRoute(deliveryId, optimizeType);
        return success(result);
    }

    /**
     * 配送预警设置
     */
    @Operation(summary = "预警设置", description = "设置配送系统预警规则")
    @PreAuthorize("@ss.hasPermi('delivery:alert')")
    @Log(title = "配送预警", businessType = BusinessType.UPDATE)
    @PostMapping("/alert-rule")
    public AjaxResult setAlertRule(@RequestParam String alertType,
                                  @RequestParam String condition,
                                  @RequestParam String threshold,
                                  @RequestParam(required = false) String notifyUsers) {
        boolean result = deliveryService.setAlertRule(alertType, condition, threshold, notifyUsers);
        return toAjax(result);
    }

    /**
     * 获取异常配送列表
     */
    @Operation(summary = "异常配送列表", description = "获取存在异常的配送订单列表")
    @PreAuthorize("@ss.hasPermi('delivery:exception:list')")
    @GetMapping("/exceptions")
    public TableDataInfo getExceptions(@RequestParam(required = false) String exceptionType,
                                      @RequestParam(required = false) String status,
                                      @RequestParam(required = false) String startDate,
                                      @RequestParam(required = false) String endDate) {
        startPage();
        List<Map<String, Object>> list = deliveryService.getExceptionDeliveries(exceptionType, status, startDate, endDate);
        return getDataTable(list);
    }

    /**
     * 处理配送异常
     */
    @Operation(summary = "处理配送异常", description = "处理配送过程中的异常情况")
    @PreAuthorize("@ss.hasPermi('delivery:exception:handle')")
    @Log(title = "配送异常", businessType = BusinessType.UPDATE)
    @PostMapping("/handle-exception")
    public AjaxResult handleException(@RequestParam Long deliveryId,
                                     @RequestParam String exceptionType,
                                     @RequestParam String solution,
                                     @RequestParam(required = false) String remark) {
        boolean result = deliveryService.handleException(deliveryId, exceptionType, solution, remark);
        return toAjax(result);
    }

    /**
     * 配送数据导出
     */
    @Operation(summary = "导出配送数据", description = "导出配送信息到Excel")
    @PreAuthorize("@ss.hasPermi('delivery:export')")
    @Log(title = "配送管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, DeliveryOrder deliveryOrder) {
        List<DeliveryOrder> list = deliveryService.selectDeliveryList(deliveryOrder);
        ExcelUtil<DeliveryOrder> util = new ExcelUtil<DeliveryOrder>(DeliveryOrder.class);
        util.exportExcel(response, list, "配送数据");
    }

    /**
     * 配送数据导入
     */
    @Operation(summary = "导入配送数据", description = "从Excel导入配送信息")
    @PreAuthorize("@ss.hasPermi('delivery:import')")
    @Log(title = "配送管理", businessType = BusinessType.IMPORT)
    @PostMapping("/import")
    public AjaxResult importData(MultipartFile file) throws Exception {
        ExcelUtil<DeliveryOrder> util = new ExcelUtil<DeliveryOrder>(DeliveryOrder.class);
        List<DeliveryOrder> deliveryList = util.importExcel(file.getInputStream());
        String message = deliveryService.importDeliveries(deliveryList);
        return success(message);
    }

    /**
     * 批量更新配送状态
     */
    @Operation(summary = "批量更新状态", description = "批量更新多个配送订单的状态")
    @PreAuthorize("@ss.hasPermi('delivery:batch:update')")
    @Log(title = "配送管理", businessType = BusinessType.UPDATE)
    @PutMapping("/batch-status-update")
    public AjaxResult batchUpdateStatus(@RequestParam Long[] deliveryIds,
                                       @RequestParam String status,
                                       @RequestParam(required = false) String remark) {
        boolean result = deliveryService.batchUpdateStatus(deliveryIds, status, remark);
        return toAjax(result);
    }

    /**
     * 配送时效分析
     */
    @Operation(summary = "时效分析", description = "分析配送时效性能")
    @PreAuthorize("@ss.hasPermi('delivery:timeliness')")
    @GetMapping("/timeliness-analysis")
    public AjaxResult getTimelinessAnalysis(@RequestParam(required = false) String startDate,
                                           @RequestParam(required = false) String endDate,
                                           @RequestParam(required = false) String region,
                                           @RequestParam(required = false) String timeType) {
        Map<String, Object> analysis = deliveryService.getTimelinessAnalysis(startDate, endDate, region, timeType);
        return success(analysis);
    }

    /**
     * 配送成本分析
     */
    @Operation(summary = "成本分析", description = "分析配送成本构成")
    @PreAuthorize("@ss.hasPermi('delivery:cost')")
    @GetMapping("/cost-analysis")
    public AjaxResult getCostAnalysis(@RequestParam(required = false) String startDate,
                                     @RequestParam(required = false) String endDate,
                                     @RequestParam(required = false) String costType,
                                     @RequestParam(required = false) String groupBy) {
        Map<String, Object> analysis = deliveryService.getCostAnalysis(startDate, endDate, costType, groupBy);
        return success(analysis);
    }

    /**
     * 配送质量分析
     */
    @Operation(summary = "质量分析", description = "分析配送服务质量")
    @PreAuthorize("@ss.hasPermi('delivery:quality')")
    @GetMapping("/quality-analysis")
    public AjaxResult getQualityAnalysis(@RequestParam(required = false) String startDate,
                                        @RequestParam(required = false) String endDate,
                                        @RequestParam(required = false) Long driverId,
                                        @RequestParam(required = false) String qualityType) {
        Map<String, Object> analysis = deliveryService.getQualityAnalysis(startDate, endDate, driverId, qualityType);
        return success(analysis);
    }

    /**
     * 智能推荐配送方案
     */
    @Operation(summary = "智能推荐", description = "基于AI算法推荐最优配送方案")
    @PreAuthorize("@ss.hasPermi('delivery:recommend')")
    @PostMapping("/recommend-plan")
    public AjaxResult recommendPlan(@RequestParam Long orderId,
                                   @RequestParam(required = false) String planType,
                                   @RequestParam(required = false) Integer topN) {
        List<Map<String, Object>> recommendations = deliveryService.recommendPlan(orderId, planType, topN);
        return success(recommendations);
    }

    /**
     * 配送性能优化
     */
    @Operation(summary = "性能优化", description = "优化配送系统性能")
    @PreAuthorize("@ss.hasPermi('delivery:optimize:performance')")
    @Log(title = "配送优化", businessType = BusinessType.UPDATE)
    @PostMapping("/optimize-performance")
    public AjaxResult optimizePerformance(@RequestParam(required = false) String optimizeType,
                                         @RequestParam(required = false) String targetMetric) {
        Map<String, Object> result = deliveryService.optimizePerformance(optimizeType, targetMetric);
        return success(result);
    }

    /**
     * 配送健康检查
     */
    @Operation(summary = "健康检查", description = "检查配送系统健康状态")
    @PreAuthorize("@ss.hasPermi('delivery:health')")
    @GetMapping("/health-check")
    public AjaxResult healthCheck() {
        Map<String, Object> healthStatus = deliveryService.healthCheck();
        return success(healthStatus);
    }

    /**
     * 配送数据同步
     */
    @Operation(summary = "数据同步", description = "同步配送相关数据")
    @PreAuthorize("@ss.hasPermi('delivery:sync')")
    @Log(title = "数据同步", businessType = BusinessType.UPDATE)
    @PostMapping("/sync-data")
    public AjaxResult syncData(@RequestParam(required = false) String syncType,
                              @RequestParam(required = false) String startDate,
                              @RequestParam(required = false) String endDate) {
        boolean result = deliveryService.syncData(syncType, startDate, endDate);
        return toAjax(result);
    }

    /**
     * 配送缓存刷新
     */
    @Operation(summary = "缓存刷新", description = "刷新配送系统缓存")
    @PreAuthorize("@ss.hasPermi('delivery:cache:refresh')")
    @Log(title = "缓存刷新", businessType = BusinessType.UPDATE)
    @PostMapping("/refresh-cache")
    public AjaxResult refreshCache(@RequestParam(required = false) String cacheType) {
        boolean result = deliveryService.refreshCache(cacheType);
        return toAjax(result);
    }
}